package com.lfy.modules.safety.statistics.vistor;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.lfy.domain.anno.Describe;
import com.lfy.modules.blog.service.UserService;
import com.lfy.modules.common.domain.entity.UserEntity;
import com.lfy.modules.common.utils.RequestUtil;
import com.lfy.modules.safety.domain.BlogVisitorRecord;
import com.lfy.modules.safety.domain.vo.VisitorLogVO;
import com.lfy.modules.safety.domain.vo.VisitorVO;
import com.lfy.modules.safety.mapper.BlogVisitorRecordMapper;
import com.lfy.modules.safety.service.BlogVisitorRecordService;

import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
@Slf4j
@Describe("分区统计独立访客持久化")
public class VisitorRecordCache implements Job {
    private static final BlogVisitorRecordService VISITOR_RECORD_SERVICE ;
    private static final UserService USER_SERVICE;
    static {
        VISITOR_RECORD_SERVICE = SpringUtil.getBean(BlogVisitorRecordService.class);
        USER_SERVICE = SpringUtil.getBean(UserService.class);
    }
    private static final Cache<String, CopyOnWriteArraySet<String>> VISITOR_CACHE = Caffeine.newBuilder()
            .initialCapacity(16)
            .expireAfterWrite(2, TimeUnit.DAYS)
            .maximumSize(10_000)
            .build();

    public static void addVisitor(String url) {
        CopyOnWriteArraySet<String> set = VISITOR_CACHE.get(url, v -> new CopyOnWriteArraySet<String>());
        assert set != null;
        set.add(RequestUtil.getIp());
    }
    public static void clearVisitor(String url) {
        VISITOR_CACHE.invalidate(url);
    }
    public static void clearAllVisitor() {
        VISITOR_CACHE.invalidateAll();
    }
    public static int getVisitorCount(String url) {
        CopyOnWriteArraySet<String> set = VISITOR_CACHE.getIfPresent(url);
        return set == null? 0 : set.size();
    }
    public static List<VisitorVO> getYesterdayBetweenSevenCount(String url){
        ArrayList<VisitorVO> result = new ArrayList<>();
        //今天
        LocalDate now = LocalDate.now();
        VisitorVO visitorVO = new VisitorVO();
        visitorVO.setCount(getVisitorCount(url));
        visitorVO.setDate(now.toString());
        result.add(visitorVO);
        for (int i = 0; i < 7; i++) {
            //TODO 循环查库
            //昨天
            visitorVO = new VisitorVO();
//            log.info("查询 {}到{}的访客数", offsetDay(i + 1), offsetDay(i));
            int count = VISITOR_RECORD_SERVICE.count(new LambdaQueryWrapper<BlogVisitorRecord>().between(BlogVisitorRecord::getCreateTime, offsetDay(i + 1), offsetDay(i)));
            visitorVO.setCount(count);
            visitorVO.setDate(now.minusDays(i+1).toString());
            result.add(visitorVO);
        }

        return result;
    }
    public static List<VisitorLogVO> getVisitorLog(UserEntity userEntity, String date){
        if(date == null || "".equals(date)){
            return null;
        }
        String nowDate = LocalDate.now().toString();
        //如果是今天，从缓存中获取数据
        if(date.equals(nowDate)){
            CopyOnWriteArraySet<String> set = VISITOR_CACHE.getIfPresent(userEntity.getUrl());
            if(CollectionUtils.isEmpty(set)){
                return null;
            }

            List<VisitorLogVO> result = new ArrayList<>();
            for (String ip : set) {
                VisitorLogVO visitorLogVO = new VisitorLogVO();
                visitorLogVO.setIp(ip);
                visitorLogVO.setIpAddress(RequestUtil.getPlace(ip));
                visitorLogVO.setDate(date);
                result.add(visitorLogVO);
            }
            return result;
        }
        //如果不是今天，从数据库中获取数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 解析日期部分
        LocalDate parsedDate = LocalDate.parse(date, formatter);

        // 将LocalDate转换为LocalDateTime，并设置时间为00:00:00
        LocalDateTime dateTime = parsedDate.atStartOfDay();
        List<BlogVisitorRecord> list = VISITOR_RECORD_SERVICE.list(new LambdaQueryWrapper<BlogVisitorRecord>().eq(BlogVisitorRecord::getTenantId, userEntity.getId()).between(BlogVisitorRecord::getCreateTime, dateTime, dateTime.plusDays(1)).orderByDesc(BlogVisitorRecord::getCreateTime));
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        List<VisitorLogVO> result = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (BlogVisitorRecord blogVisitorRecord : list) {
            VisitorLogVO visitorLogVO = new VisitorLogVO();
            visitorLogVO.setIp(blogVisitorRecord.getIp());
            visitorLogVO.setIpAddress(blogVisitorRecord.getIpAddress());
            Date createTime = blogVisitorRecord.getCreateTime();
            visitorLogVO.setDate(simpleDateFormat.format(createTime));
            result.add(visitorLogVO);
        }
        return result;
    }
    public static String offsetDay(int day){
        LocalDateTime nano = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        return nano.minusDays(day).toString();

    }


    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        try {
            List<BlogVisitorRecord> list = new ArrayList<>();
            List<UserEntity> userEntities = USER_SERVICE.list();
            VISITOR_CACHE.asMap().forEach((key, value) -> {
                Long tenantId = null;
                for (UserEntity userEntity : userEntities) {
                    if(userEntity.getUrl().equals(key)){
                        tenantId = userEntity.getId();
                    }
                }
                if (Objects.nonNull(tenantId)){
                    for (String ip : value) {
                        BlogVisitorRecord blogVisitorRecord = new BlogVisitorRecord();
                        blogVisitorRecord.setTenantId(tenantId);
                        blogVisitorRecord.setIp(ip);
                        blogVisitorRecord.setIpAddress(RequestUtil.getPlace(ip));
                        list.add(blogVisitorRecord);
                    }
                }

            });
            if(list.size() > 0){
                VISITOR_RECORD_SERVICE.saveBatch(list);
            }
            clearAllVisitor();
        } catch (Exception e) {
            log.error("分区统计独立访客持久化失败");
        }
    }
}
